#!/bin/bash -e
#
#   Neutron3529's Unity Game Plugin
#   Copyright (C) 2022 Neutron3529
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as
#   published by the Free Software Foundation, either version 3 of the
#   License, or (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
############################################################################
#
#   * compile instructions: put this file and `utils.cs` in `steamapps`
#   * folder, open a terminal in the same folder, and execute:
#   *
#   * ```
#   *     chmod +x ${file}.cs
#   *     ./${file}.cs
#   * ```
#   *
#   * then the mod will be compiled automatically.
#   *
#   * Here we wrote a shebang like file, which is correct
#   * in my computer (Manjaro XFCE), if such script do not work
#   * in your computer, you could just try the instructions below :

export GAME_NAME="ReverseCollapse_beta"                                # might modify if the name mismatch.
export GAME_DIR="$GAME_NAME"                                # might be modified, but "$GAME_NAME" cover most of the cases.

export FILE_NAME="$0"
export ASSEMBLY="Assembly-CSharp"                           # might be modified
export UTILS="utils.cs"                                     # might be modified if you do not put utils.cs in the current dir.
export PLUGIN_ID="Neutron3529.Cheat"                        # should be modified
export NAMESPACE_ID="Neutron3529.Cheat"                     # should be modified
export GAME_BASE_DIR="common/ReverseCollapse Demo/windows_betax"                     # should modify GAME_DIR instead since GAME_DIR == GAME_NAME is almost always true.

export IFS=$'\n' # to disable the annoying space.
export DOTNET="dotnet" # the location of the DOTNET executable file.
[ -z "$DOTNET_CSC_DLL" ] && export DOTNET_CSC_DLL=`\ls /usr/share/dotnet/sdk/*/Roslyn/bincore/csc.dll` # In manjaro, the csc.dll is located in /usr/share/dotnet/sdk/*/Roslyn/bincore/csc.dll

case $1 in
    V)       EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    v)       EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    VERBOSE) EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    verbose) EXTRA_DEFINE="-define:DEBUG${IFS}-define:VERBOSE${IFS}-debug" ;;
    D)       EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    d)       EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    DEBUG)   EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    debug)   EXTRA_DEFINE="-define:DEBUG${IFS}-debug"                      ;;
    *)       EXTRA_DEFINE=""                                               ;;
esac

_MODE__SELECT_=100

( yes "" | head -n $_MODE__SELECT_ | head -n-1  ; tail $FILE_NAME -n+$_MODE__SELECT_) | sed s/%%NAMESPACE_ID%%/${NAMESPACE_ID}/g | sed s/%%PLUGIN_ID%%/${PLUGIN_ID}/g | $DOTNET $DOTNET_CSC_DLL -nologo -t:library \
  -r:"${GAME_BASE_DIR}/BepInEx/core/0Harmony.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.Core.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.IL2CPP.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/UnhollowerBaseLib.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/Il2Cppmscorlib.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/Il2CppSystem.Core.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/UnityEngine.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/UnityEngine.UI.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/unhollowed/UnityEngine.CoreModule.dll" \
  $(for i in "${GAME_BASE_DIR}/BepInEx/unhollowed/$ASSEMBLY"*.dll ; do echo -e "-r:\"$i\"\n" ; done) \
  `[ -e "${GAME_BASE_DIR}/mono/Managed/netstandard.dll" ] && echo "-r:\"${GAME_BASE_DIR}/mono/Managed/netstandard.dll\""` \
  -r:"${GAME_BASE_DIR}/mono/Managed/System.dll" \
  -r:"${GAME_BASE_DIR}/mono/Managed/System.Core.dll" \
  -r:"${GAME_BASE_DIR}/mono/Managed/mscorlib.dll" \
  -out:"${GAME_BASE_DIR}/BepInEx/plugins/${FILE_NAME%.*}".dll \
  -optimize $EXTRA_DEFINE \
  - $UTILS && rm -f "${GAME_BASE_DIR}/BepInEx/config/${PLUGIN_ID}.cfg";

if [ -n "$2" ]; then
    git add ${FILE_NAME}
    case $2 in
        R) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        r) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        RANDOM) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        random) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        U) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        u) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        UPLOAD) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        upload) git commit -am "`curl -s https://whatthecommit.com/index.txt`" ;;
        *) git commit -am "$2" ;;
    esac
    git push
fi
exit



using Il2CppSystem;
using System.Linq;
using Il2CppSystem.Reflection;
using Il2CppSystem.Reflection.Emit;
using Il2CppSystem.Collections.Generic;

using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

namespace %%NAMESPACE_ID%%;

[BepInPlugin("%%PLUGIN_ID%%", "%%NAMESPACE_ID%%", "0.1.0")]
public class Cheat : Neutron3529.ModEntry {
    public Cheat() : base("%%PLUGIN_ID%%") {}
    public override void Awake() {
        base.Awake();
        // Mafi.Localization.LocalizationManager.EnableLocalization(); // 不知道为什么不加这一句会导致游戏变成纯英文
        // 主要逻辑放在`utils.cs`中，这里的Awake2只是为了以防万一
        // 目前来说，这个函数的唯一用途是用来“叮”……
        // 就像这样：
        logger("叮~修改器启动，请安心游戏");
    }
    [Desc("可操控人物")]
    class 可操控人物 : Const {
        // [Desc("可操控人物，以竖线分割，尽可填写ID")]
        // string names="10000|10100|11310|11314|11000|11100"; // 11310:武器站 11314:侦查机
        // static int[] list=new int[0];
        // public override void Enable(){
        //     list=(from x in (names.Split('|')) select int.Parse(x)).ToArray();
        //     foreach(var x in list){
        //         logger($"可操控人物 got {x}");
        //     }
        // }
        public static bool Contains(RCGame.UnitBattle __instance){
            // logger($"check {__instance.tableRow.name} {__instance.tableRow.name_short} {__instance.tableRow.group} {__instance.unitId} tableId={__instance.tableId} {__instance.unitData.TableId} ret {__instance.isInPlayerControl}");
            return __instance.isInPlayerControl && __instance.tableRow.group==0;
        } // 可操控人物.list.Contains(__instance.tableId) || 可操控人物.list.Contains(__instance.unitData.TableId);
    }
    [Desc("必定暴击")]
    [HarmonyPatch(typeof(RCGame.UnitBattle),"GetBaseCritical")]
    class 必定暴击 : Entry {
        static int Postfix(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取暴击: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret}");
                return 1000;
            }
            return 0;
        }
    }
    [Desc("必定命中")]
    [HarmonyPatch(typeof(RCGame.UnitBattle),"GetSelfHit")]
    class 必定命中 : Entry {
        static int Postfix(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取命中: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret}");
                return 1000;
            }
            return ret;
        }
    }
    [HarmonyPatch(typeof(RCGame.UnitBattle),"GetBaseSightRange")]
    class 视野 : Entry {
        [Desc("视野加值")]
        static int add=-1;
        static int Postfix(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取视野: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret} GetBaseStealthRange={__instance.GetBaseStealthRange()} GetSightType={__instance.GetSightType()} GetSelfStealthRange={__instance.GetSelfStealthRange()} GetDetectionRange={__instance.GetDetectionRange()} GetMineRange={__instance.GetMineRange()} GetTrueSightRange={__instance.GetTrueSightRange()} GetTrueSightHideRange={__instance.GetTrueSightHideRange()} GetRawStealthRange={__instance.GetRawStealthRange(true)} ");
                ret+=add;
            }
            return ret;
        }
    }
    class 反潜视野 : Entry {
        [Desc("反潜视野加值")]
        static int add=10;
        [HarmonyPostfix, HarmonyPatch(typeof(RCGame.UnitBattle),"GetBaseStealthRange")]
        static int Postfix1(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取反潜视野: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret}");
                ret+=add;
            }
            return ret;
        }
        [HarmonyPostfix, HarmonyPatch(typeof(RCGame.UnitBattle),"GetDetectionRange")]
        static int Postfix2(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取反潜视野: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret}");
                ret+=add;
            }
            return ret;
        }
    }
    class 反隐视野 : Entry {
        [Desc("反隐视野加值")]
        static int add=10;
        [HarmonyPostfix, HarmonyPatch(typeof(RCGame.UnitBattle),"GetSightHideRange")]
        static int p1(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取反隐视野: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret}");
                ret+=add;
            }
            return ret;
        }
        [HarmonyPostfix, HarmonyPatch(typeof(RCGame.UnitBattle),"GetMineRange")]
        static int p3(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取反隐视野: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret}");
                ret+=add;
            }
            return ret;
        }
        [HarmonyPostfix, HarmonyPatch(typeof(RCGame.UnitBattle),"GetTrueSightRange")]
        static int p4(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取反隐视野: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret}");
                ret+=add;
            }
            return ret;
        }
        [HarmonyPostfix, HarmonyPatch(typeof(RCGame.UnitBattle),"GetTrueSightHideRange")]
        static int p5(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取反隐视野: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret}");
                ret+=add;
            }
            return ret;
        }
    }
    [HarmonyPatch(typeof(RCGame.UnitBattle),"GetMaxAp")]
    class 最大AP : Entry {
        [Desc("最大AP加值")]
        static int add=25;
        static int Postfix(int ret, RCGame.UnitBattle __instance){
            if(可操控人物.Contains(__instance)){
                // logger($"读取最大AP加值: isInPlayerControl:{__instance.isInPlayerControl}({__instance.unitId} {__instance.tableId} {__instance.unitData.TableId}) val={ret}");
                ret+=add;
            }
            return ret;
        }
    }
    [Desc("学习技能不消耗基因潜能")]
    [HarmonyPatch(typeof(RCGame.CharacterData),"DoGeneUpgrade")]
    class 学习技能不消耗基因潜能 : Entry {
        static void Prefix(RCGame.CharacterData __instance, int gene_id, int level){
            __instance.GetGeneData(gene_id).rowData.cost_genepoint=0;
            // logger($"获取到的基因equipIdx：{__instance.GetGeneData(gene_id).equipIdx}");
            // logger($"获取到的基因gene_id：{__instance.GetGeneData(gene_id).gene_id}");
            // logger($"获取到的基因level：{__instance.GetGeneData(gene_id).level}");
            // logger($"获取到的基因rowData.level：{__instance.GetGeneData(gene_id).rowData.level}");
            // logger($"获取到的基因rowData.player_level：{__instance.GetGeneData(gene_id).rowData.player_level}");
            // logger($"获取到的基因rowData.cost_genepoint{__instance.GetGeneData(gene_id).rowData.cost_genepoint}");
            // logger($"获取到的基因rowData.keys_secret.Count{__instance.GetGeneData(gene_id).rowData.keys_secret.Count}");
            // logger($"获取到的基因rowData.logic_skill_id.Count{__instance.GetGeneData(gene_id).rowData.logic_skill_id.Count}");
            // logger($"获取到的基因rowData.mode{__instance.GetGeneData(gene_id).rowData.mode}");
            // logger($"level={level}");
            // for(int i=2;i<=5;i++){
            //     logger($"获取到的基因equipIdx：{__instance.GetGeneData(gene_id).equipIdx}");
            //     logger($"获取到的基因gene_id：{__instance.GetGeneData(gene_id).gene_id}");
            //     logger($"获取到的基因level：{__instance.GetGeneData(gene_id).level}");
            //     logger($"获取到的基因rowData.level：{__instance.GetGeneData(gene_id).rowData.level}");
            //     logger($"获取到的基因rowData.player_level：{__instance.GetGeneData(gene_id).rowData.player_level}");
            //     __instance.GetGeneData(gene_id).rowData.cost_genepoint=0;
            //     __instance.SetGeneLevel(gene_id, i); // 有效
            // }
            // logger($"获取到的基因equipIdx：{__instance.GetGeneData(gene_id).equipIdx}");
            // logger($"获取到的基因gene_id：{__instance.GetGeneData(gene_id).gene_id}");
            // logger($"获取到的基因level：{__instance.GetGeneData(gene_id).level}");
            // logger($"获取到的基因rowData.level：{__instance.GetGeneData(gene_id).rowData.level}");
            // logger($"获取到的基因rowData.player_level：{__instance.GetGeneData(gene_id).rowData.player_level}");
            //
            // // __instance.AddGeneRedPoint(10);
            // return false;
        }
        // static void Postfix(RCGame.CharacterData __instance, int gene_id, int level){
        //     // __instance.GetGeneData(gene_id).rowData.player_level=1; //无效
        //     __instance.GetGeneData(gene_id).rowData.cost_genepoint=0;
        //     // __instance.SetGeneLevel(gene_id, Math.Max(3,level)); // 有效
        //     // // __instance.AddGeneRedPoint(10);
        //     // return false;
        // }
    }
}
